﻿using B.S.RbacData.Domain;
using B.S.RbacData.ErrorCode;
using B.S.RbacData.Infrastructure;
using B.S.RbacData.Read.API.Applications.Commands;
using B.S.RbacData.Read.API.Dtos;
using MediatR;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Microsoft.IdentityModel.Tokens;
using Newtonsoft.Json;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Text;

namespace B.S.RbacData.Read.API.Applications.CommandHandlters
{
    /// <summary>
    /// 登录命令处理
    /// </summary>
    public class LoginCommandHandlter : IRequestHandler<LoginCommand, ApiResult<LoginDtos>>
    {
        private readonly IBaseRepository<UserModel> _userRepository;
        private readonly IBaseRepository<UserRoleModel> _userRoleRepository;
        private readonly IBaseRepository<RoleModel> _roleRepository;
        private readonly IConfiguration _configuration;
        private readonly IHttpContextAccessor _httpContextAccessor;

        public LoginCommandHandlter(
            IBaseRepository<UserModel> userRepository,
            IBaseRepository<UserRoleModel> userRoleRepository,
            IBaseRepository<RoleModel> roleRepository, IConfiguration configuration,IHttpContextAccessor httpContextAccessor)
        {
            _userRepository = userRepository ?? throw new ArgumentNullException(nameof(userRepository));
            _userRoleRepository = userRoleRepository ?? throw new ArgumentNullException(nameof(userRoleRepository));
            _roleRepository = roleRepository ?? throw new ArgumentNullException(nameof(roleRepository));
            _configuration = configuration;
            _httpContextAccessor = httpContextAccessor;
        }

        public async Task<ApiResult<LoginDtos>> Handle(LoginCommand request, CancellationToken cancellationToken)
        {
            if (string.IsNullOrEmpty(request.UserName) || string.IsNullOrEmpty(request.Password))
            {
                return new ApiResult<LoginDtos>
                {
                    code = ResultEnumCode.fails,
                    message = "用户名或密码不能为空",
                    data = null
                };
            }

            var user = await _userRepository.GetAll()
                .Where(x => x.UserName == request.UserName && !x.IsDeleted)
                .FirstOrDefaultAsync(cancellationToken);

            if (user == null)
            {
                return new ApiResult<LoginDtos>
                {
                    code = ResultEnumCode.fails,
                    message = "用户不存在",
                    data = null
                };
            }

            if (user.Password != request.Password)
            {
                return new ApiResult<LoginDtos>
                {
                    code = ResultEnumCode.fails,
                    message = "密码错误！",
                    data = null
                };
            }

            var userRoleIds = await _userRoleRepository.GetAll()
                .Where(x => !x.IsDeleted && x.UserId == user.ID)
                .Select(x => x.RoleId)
                .ToListAsync(cancellationToken);


            var roleNames = new List<string>();
            var loginDtosList = new List<LoginDtos>();

            // 先收集所有角色名称
            foreach (var roleId in userRoleIds)
            {
                var role = await _roleRepository.GetAll()
                    .Where(x => x.ID == roleId && !x.IsDeleted)
                    .Select(x => x.RoleName)
                    .FirstOrDefaultAsync(cancellationToken);

                if (role != null)
                {
                    roleNames.Add(role);
                }
            }




            // 将所有角色名称合并为以逗号分隔的字符串
            string allRolesString = string.Join(",", roleNames);

            var token = GenerateJwtToken(user);

            // 创建DTO对象
            foreach (var roleId in userRoleIds)
            {
                var role = await _roleRepository.GetAll()
                    .Where(x => x.ID == roleId && !x.IsDeleted)
                    .Select(x => x.RoleName)
                    .FirstOrDefaultAsync(cancellationToken);

                if (role != null)
                {
                    loginDtosList.Add(new LoginDtos
                    {   

                        RoleId= JsonConvert.SerializeObject(userRoleIds),
                        UserId = user.ID,
                        UserName = user.UserName,
                        AllRoles = allRolesString,
                        token = token.AccessToken,
                        refreshtoken =token.RefreshToken,
                    });
                }
            }


           

            return new ApiResult<LoginDtos>
            {
                code = ResultEnumCode.Ok,
                message = "登录成功",
                data = loginDtosList.FirstOrDefault()
            };
        }


        /// <summary>
        /// 生成JWT令牌
        /// </summary>
        /// <param name="user"></param>
        /// <returns></returns>
        public TokenResponse GenerateJwtToken(UserModel user)
        {
            var securityKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_configuration["JwtSettings:SecretKey"]));
            var credentials = new SigningCredentials(securityKey, SecurityAlgorithms.HmacSha256);

            var claims = new[]
            {
                new Claim("UserName", user.UserName),
                new Claim("UserId", user.ID.ToString()),
                new Claim("RoleId","1"),
                new Claim("RoleName","")
            };

            var token = new JwtSecurityToken(
                issuer: _configuration["JwtSettings:Issuer"],
                audience: _configuration["JwtSettings:Audience"],
                claims: claims,
                //AccessTokenExpirationMinutes
                //token过期时间
                expires: DateTime.Now.AddMinutes(Convert.ToDouble(_configuration["JwtSettings:AccessTokenExpirationMinutes"])),
                signingCredentials: credentials
            );

            // 生成授权token 字符串
            var strToken = new JwtSecurityTokenHandler().WriteToken(token);

            //生成 续期Token 创建refresh token
            var refreshToken = new RefreshToken
            {
                Token = Guid.NewGuid().ToString("N"),
                Expires = DateTime.UtcNow.AddDays(Convert.ToDouble(_configuration["JwtSettings:RefreshTokenExpirationDays"])),
                Created = DateTime.UtcNow,
                UserId = user.ID // 使用传入的用户ID，而不是从HttpContext获取
            };

            return new TokenResponse()
            {
                AccessToken = strToken,
                RefreshToken = JsonConvert.SerializeObject(refreshToken)
            };
        }
    }
}
